package com.hxzy.service.impl;

import cn.hutool.core.util.IdUtil;
import com.fasterxml.jackson.databind.annotation.JsonAppend;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.common.exception.ServiceStringException;
import com.hxzy.controller.seckill.req.SeckillReq;
import com.hxzy.entity.Orders;
import com.hxzy.entity.StoreCount;
import com.hxzy.service.OrdersService;
import com.hxzy.service.SeckillService;
import com.hxzy.service.StoreCountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Author wy
 * @Description redis来实现的
 * @Date 2023/9/11 11:34
 * @Version 1.0
 */
@Service
public class RedisSeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StoreCountService  storeCountService;
    @Autowired
    private OrdersService  ordersService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long seckill(SeckillReq req) {
        //下订单
        Orders orders = new Orders();

        //加分布式锁   set   key  value   nx
        String redisKey = "seckill:" + req.getStockId();
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(redisKey, "秒杀");
        //加锁成功
        if (absent) {
            StoreCount db = this.storeCountService.getById(1000);
            if (db == null) {
                //释放锁
                redisTemplate.delete(redisKey);
                throw new ServiceException(AckCode.NOT_FOUND_DATA);
            }

            //库存不足
            if (db.getStore() < req.getCount()) {
                redisTemplate.delete(redisKey);
                throw new ServiceException(AckCode.SCKILL_NOT_NUM);
            }

            try{

                //更新库存,如果这里有异常，redis 锁不会被删除
                boolean result=this.storeCountService.updateSckill(req);
                if(result) {
                    //订单号
                    orders.setOrderId(IdUtil.getSnowflakeNextId());
                    orders.setUserId(req.getUserId());
                    orders.setStockId(req.getStockId());
                    orders.setNum(req.getCount());
                    orders.setCreateTime(new Date());
                    this.ordersService.save(orders);
                }else{
                    //库存不足
                    throw new ServiceException(AckCode.SCKILL_NOT_SUCCESS);
                }

            }catch (Exception e){
                throw new ServiceStringException(e.getMessage());
            }finally {
                //释放锁
                redisTemplate.delete(redisKey);
            }
        } else {
            //加锁不成功
            throw new ServiceException(AckCode.SCKILL_LOCK_FAILED);
        }
        //返回订单号
        return orders.getOrderId();
    }
}
